package org.infodavid.common.impl.tasks;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.infodavid.common.util.AbstractProcessor;
import org.infodavid.common.util.HelperUtil;
import org.infodavid.common.util.IVisitor;

/**
 * The Class AbstractTasksProcessor.
 */
@SuppressWarnings("rawtypes")
public abstract class AbstractTasksProcessor extends AbstractProcessor {

    /** The Constant log. */
    private static final Log LOGGER = LogFactory.getLog(AbstractTasksProcessor.class);

    /** The tasks. */
    private final List<IVisitor> tasks = new ArrayList<IVisitor>();

    /**
     * Instantiates a new processor.
     */
    protected AbstractTasksProcessor() {
        super();
    }

    /**
     * Gets the tasks.
     * @return the tasks
     */
    public List<IVisitor> getTasks() {
        return tasks;
    }

    /**
     * Initialize.
     * @param <T> the input data
     * @param data the data
     * @throws Throwable the error
     */
    protected <T extends Object> void initialize(final T data) throws Throwable {
        LOGGER.info(tasks.size() + " tasks to initialize");

        for (final IVisitor task : tasks) {
            LOGGER.info("Processing task: " + task);

            try {
                task.initialize();

                LOGGER.info("Task initialized");
            }
            catch (final Exception e) {
                if (isFailOnError()) {
                    throw e;
                }

                LOGGER.error("An error occurs while initializing task", e);
            }
        }
    }

    /**
     * Execute.
     * @param <T> the input data
     * @param data the data
     * @throws Throwable the error
     */
    @SuppressWarnings("unchecked")
    protected <T extends Object> void execute(final T data) throws Throwable {
        final HelperUtil util = HelperUtil.getInstance();
        final int retryCount = getRetryCount();
        final long retryPeriod = getRetryPeriod();
        int success = 0;
        int failed = 0;

        LOGGER.info(tasks.size() + " tasks to process");

        for (final IVisitor task : tasks) {
            LOGGER.info("Processing task: " + task);

            try {
                util.execute(task, data, retryCount, retryPeriod);
                success++;

                LOGGER.info("Task completed");
            }
            catch (final Exception e) {
                failed++;

                if (isFailOnError()) {
                    throw e;
                }

                LOGGER.error("An error occurs while processing task", e);
            }
        }

        LOGGER.info(success + " task(s) completed, " + failed + " task(s) failed");
    }
}
